Skip to content

[build-tools] replace record-sim with serve-sim recording - #4474

Draft
gwdp wants to merge 1 commit into
mainfrom
gabe/serve-sim-recording-consumer
Draft

gwdp wants to merge 1 commit into
mainfrom
gabe/serve-sim-recording-consumer

Conversation

@gwdp

@gwdp gwdp commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Why

The session runner used record-sim to capture the framebuffer separately from serve-sim. The new serve-sim stack owns one native capture and a dedicated hardware recording encoder, so build-tools can use its recording client and keep the existing upload manifest.

Depends on expo/serve-sim#208 and its lower stack layers being released first.

How

Start serve-sim record-video from the selected serve-sim package after its token-bearing preview is ready, wait for its start marker, and stop with SIGINT. Recording begins with that preview; footage before serve-sim startup is outside this recording. If serve-sim stops first, it finalizes the file during shutdown while the client waits for the manifest. Give the serve-sim process group up to 90 seconds after SIGTERM before SIGKILL, even when its package-manager wrapper exits early. Remove record-sim packaging; the upload step is unchanged.

Test Plan

  • corepack yarn jest-unit --runInBand src/steps/utils/__tests__/IosSimulatorRecordingUtils.test.ts src/steps/utils/__tests__/remoteDeviceRunSession.test.ts: 74 passed.
  • corepack yarn typecheck in build-tools, root corepack yarn lint, and root corepack yarn fmt:check: passed.
  • The matching local serve-sim binary produced a decodable MP4 and the existing manifest in pinned Tart iPhone 17, Xcode 26.4, with two concurrent H.264 viewers. A separate SIGTERM run confirmed finalization and client manifest wait.
  • Hosted EAS worker execution remains unverified. Release serve-sim before this consumer.

— Codex

@gwdp gwdp added the no changelog PR that doesn't require a changelog entry label Sep 25, 2026
@codecov

codecov Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.53608% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.64%. Comparing base (b1f886e) to head (1815695).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...ools/src/steps/utils/IosSimulatorRecordingUtils.ts 81.02% 15 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4474      +/-   ##
==========================================
+ Coverage   72.42%   72.64%   +0.22%     
==========================================
  Files         975      975              
  Lines       46617    46688      +71     
  Branches    10069    10082      +13     
==========================================
+ Hits        33760    33912     +152     
+ Misses      11857    11786      -71     
+ Partials     1000      990      -10     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gwdp
gwdp force-pushed the gabe/serve-sim-recording-consumer branch from a0f3012 to 1815695 Compare September 25, 2026 18:03
@github-actions

Copy link
Copy Markdown

⏩ The changelog entry check has been skipped since the "no changelog" label is present.

@gwdp

gwdp commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

/devin review

@devin-ai-integration

Copy link
Copy Markdown

Starting Devin Review.

Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 potential issues.

Devin Review

Comment thread packages/build-tools/src/steps/utils/IosSimulatorRecordingUtils.ts
Comment thread packages/build-tools/src/steps/utils/IosSimulatorRecordingUtils.ts Outdated
Comment on lines +314 to +319
.then(async () => {
try {
await access(path.join(outputDirectory, 'session.json'));
} catch {
scheduleRecordingRetry(session, udid);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Late manifests trigger duplicate recordings

If session.json appears after a successful client exit, completionPromise schedules a retry despite the later manifest wait. The poller can start another recording for the same server token, producing duplicate session recordings.

Learn more

A recorder's process exit and the manifest's appearance are treated as separate events by waitForRecordingManifestAsync, which allows 30 seconds for the manifest. This immediate post-exit check instead counts a temporarily absent manifest as a failed attempt. pollIosSimulatorRecordingsAsync is allowed to launch another recorder after the 25-second retry delay, even if the original manifest has since appeared.

Example: The client exits at 10:00:00, and its manifest appears at 10:00:03. The access check at 10:00:00 schedules a retry at 10:00:25. If serve-sim is still registered at that point, a second recording starts despite the completed first recording.

Recommended fix: Apply the same bounded manifest grace period before scheduling a retry, or recheck the manifest immediately before restarting a recorder for an unchanged server token.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +230 to +234
const token = readyServers.get(device.udid);
const packageSpec = serveSimPackageSpecs.get(device.udid);
if (!token || !packageSpec) {
continue;
}

@devin-ai-integration devin-ai-integration Bot Sep 25, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Recording coverage depends on preview startup

A booted simulator now records only while a token-bearing serve-sim preview has registered its package. Check whether workflows need footage before preview startup or without a preview.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@gwdp gwdp Sep 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed: recording starts when a token-bearing serve-sim preview is ready, so this PR does not capture footage before that startup. I added that boundary explicitly to the PR description. It follows the planned single native capture path; restoring earlier footage would need a different owner for capture before serve-sim starts.

— Codex

Comment thread packages/build-tools/src/steps/utils/IosSimulatorRecordingUtils.ts
@gwdp
gwdp force-pushed the gabe/serve-sim-recording-consumer branch from 1815695 to cff9ab3 Compare September 25, 2026 18:22
@gwdp

gwdp commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

/devin review

@devin-ai-integration

Copy link
Copy Markdown

Starting Devin Review.

Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog PR that doesn't require a changelog entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant